import {
  app,
  BrowserWindow,
  shell,
  ipcMain,
  Menu,
  dialog,
  DownloadItem,
} from "electron";
import { release } from "node:os";
import { join } from "node:path";
import electronDl from "electron-dl";
import fs from "node:fs";
import compressing from "compressing";
import { exec } from "child_process";
import Store from "electron-store";
import { useAutoUpdater } from "./autoUpdater";
// The built directory structure
//
// ├─┬ dist-electron
// │ ├─┬ main
// │ │ └── index.js    > Electron-Main
// │ └─┬ preload
// │   └── index.js    > Preload-Scripts
// ├─┬ dist
// │ └── index.html    > Electron-Renderer
//
process.env.DIST_ELECTRON = join(__dirname, "..");
process.env.DIST = join(process.env.DIST_ELECTRON, "../dist");
process.env.VITE_PUBLIC = process.env.VITE_DEV_SERVER_URL
  ? join(process.env.DIST_ELECTRON, "../public")
  : process.env.DIST;

// Disable GPU Acceleration for Windows 7
if (release().startsWith("6.1")) app.disableHardwareAcceleration();

// Set application name for Windows 10+ notifications
if (process.platform === "win32") app.setAppUserModelId(app.getName());

if (!app.requestSingleInstanceLock()) {
  app.quit();
  process.exit(0);
}

// Remove electron security warnings
// This warning only shows in development mode
// Read more on https://www.electronjs.org/docs/latest/tutorial/security
// process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true'

let win: BrowserWindow | null = null;
// Here, you can also use other preload
const preload = join(__dirname, "../preload/index.js");
const url = process.env.VITE_DEV_SERVER_URL;
const indexHtml = join(process.env.DIST, "index.html");

useAutoUpdater();
const defaultConfig = {
  directory: join(process.env.VITE_PUBLIC, "gameLib"),
  gameDir: "",
  gameExe: "",
  clientPack: "https://vip.123pan.cn/1817485307/dnf/xigua_client_pack.zip",
  updatePacks: "https://vip.123pan.cn/1817485307/dnf/xigua_update_packs.zip",
  version: "https://vip.123pan.cn/1817485307/dnf/xigua_version.json",
  packName: "xigua_client_pack",
  exeName: "地下城与勇士[点我启动].exe",
  versionName: "xigua_version.json",
};
const store = new Store<Record<string, string>>();
function setDefault(key: string, value?: string) {
  if (!store.has(key)) {
    store.set(key, value || defaultConfig[key]);
  }
}
function initStore() {
  setDefault("directory");
  setDefault("clientPack");
  setDefault("updatePacks");
  setDefault("version");
  setDefault("packName");
  setDefault("exeName");
  setDefault("versionName");
  setDefault("gameDir", join(defaultConfig.directory, defaultConfig.packName));
  setDefault("gameExe", join(defaultConfig.directory, defaultConfig.exeName));
}
initStore();

async function createWindow() {
  Menu.setApplicationMenu(null);
  win = new BrowserWindow({
    height: 300,
    width: 600,
    title: "西瓜dnf更新工具",
    icon: join(process.env.VITE_PUBLIC, "logo.png"),
    webPreferences: {
      preload,
      // Warning: Enable nodeIntegration and disable contextIsolation is not secure in production
      // Consider using contextBridge.exposeInMainWorld
      // Read more on https://www.electronjs.org/docs/latest/tutorial/context-isolation
      nodeIntegration: true,
      contextIsolation: false,
    },
    resizable: false,
  });

  if (process.env.VITE_DEV_SERVER_URL) {
    // electron-vite-vue#298
    win.loadURL(url);
    // Open devTool if the app is not packaged
    win.webContents.openDevTools();
  } else {
    win.loadFile(indexHtml);
  }

  // Test actively push message to the Electron-Renderer
  win.webContents.on("did-finish-load", () => {
    win?.webContents.send("main-process-message", new Date().toLocaleString());
  });

  // Make all links open with the browser, not with the application
  win.webContents.setWindowOpenHandler(({ url }) => {
    if (url.startsWith("https:")) shell.openExternal(url);
    return { action: "deny" };
  });
  // win.webContents.on('will-navigate', (event, url) => { }) #344
}

app.whenReady().then(createWindow);

app.on("second-instance", () => {
  if (win) {
    // Focus on the main window if the user tried to open another
    if (win.isMinimized()) win.restore();
    win.focus();
  }
});

app.on("activate", () => {
  const allWindows = BrowserWindow.getAllWindows();
  if (allWindows.length) {
    allWindows[0].focus();
  } else {
    createWindow();
  }
});

// New window example arg: new windows url
ipcMain.handle("open-win", (_, arg) => {
  const childWindow = new BrowserWindow({
    webPreferences: {
      preload,
      nodeIntegration: true,
      contextIsolation: false,
    },
  });

  if (process.env.VITE_DEV_SERVER_URL) {
    childWindow.loadURL(`${url}#${arg}`);
  } else {
    childWindow.loadFile(indexHtml, { hash: arg });
  }
});

let downloadItem: DownloadItem;
// let cacheItem: CreateInterruptedDownloadOptions = {
//   path: "",
//   eTag: "",
//   urlChain: [],
//   length: 0,
//   offset: 0,
//   mimeType: "",
//   lastModified: "",
//   startTime: 0,
// };

// const iniPath = join(process.env.VITE_PUBLIC, "cache.ini");
app.on("window-all-closed", () => {
  win = null;
  if (process.platform !== "darwin") app.quit();
});

ipcMain.on(
  "download-button",
  async (event, info: { url: string; properties: electronDl.Options }) => {
    console.log("download", url);
    const bwin = BrowserWindow.getFocusedWindow();
    info.properties = {
      onProgress(status) {
        // cacheItem.path = downloadItem.getSavePath();
        // cacheItem.eTag = downloadItem.getETag();
        // cacheItem.urlChain = downloadItem.getURLChain();
        // cacheItem.length = status.totalBytes;
        // cacheItem.offset = status.transferredBytes;
        // cacheItem.mimeType = downloadItem.getMimeType();
        // cacheItem.lastModified = downloadItem.getLastModifiedTime();
        // cacheItem.startTime = downloadItem.getStartTime();
        win.webContents.send("download progress", status);
      },
      onStarted(item) {
        downloadItem = item;
        win.webContents.send("download start");
      },
      onCompleted(file) {
        downloadItem = null;
        win.webContents.send("download complete", file);
      },
      onCancel(item) {
        console.log("donwload cancel");
        downloadItem = null;
        // fs.writeFileSync(iniPath, JSON.stringify(cacheItem), "utf-8");
      },
      ...info.properties,
    };
    // if (fs.existsSync(iniPath)) {
    //   const str = fs.readFileSync(iniPath, "utf-8");
    //   cacheItem = JSON.parse(str);
    //   if (fs.existsSync(cacheItem.path + ".template")) {
    //     await copy(cacheItem.path + ".template", cacheItem.path);
    //   }
    //   electronDl(info.properties);
    //   session.defaultSession.createInterruptedDownload(cacheItem);
    //   return;
    // }

    electronDl.download(bwin, info.url, info.properties).catch((error) => {
      console.log("faild", error);
      win.webContents.send("download error", error);
      dialog.showMessageBox({
        type: "error",
        message: "下载出错啦，请联系管理员",
        title: "出错啦",
      });
    });
    win.on("close", async (e) => {
      e.preventDefault();
      if (downloadItem) {
        downloadItem?.pause();
        const { response } = await dialog.showMessageBox({
          type: "question",
          buttons: ["确认，我不想下了", "取消，我点错了"],
          title: "你是要关闭吗？",
          message: "有下载正在进行，退出将丢失全部进度，确认退出？",
        });
        if (response === 0) {
          win = null;
          // if (fs.existsSync(cacheItem.path)) {
          // const stats = fs.statSync(cacheItem.path);
          // console.log(stats.size);
          // await copy(cacheItem.path, cacheItem.path + ".template");
          // }
          app.exit();
        } else {
          downloadItem?.resume();
          e.preventDefault();
        }
      } else {
        app.exit();
      }
    });
  }
);

ipcMain.on("download pause", () => {
  downloadItem.pause();
});
ipcMain.on("download resume", () => {
  downloadItem.resume();
});

ipcMain.on("open directory", (event, { defaultPath }) => {
  dialog
    .showOpenDialog({ properties: ["openFile", "openDirectory"], defaultPath })
    .then((info) => {
      if (!info.canceled) {
        win.webContents.send("set path", info.filePaths[0]);
      }
    });
});
ipcMain.on("select directory", (event, type) => {
  dialog
    .showOpenDialog({
      properties: type === "dir" ? ["openFile", "openDirectory"] : ["openFile"],
      filters: type === "exe" ? [{ extensions: ["exe"], name: "" }] : [],
    })
    .then((info) => {
      if (!info.canceled) {
        win.webContents.send("select path", { path: info.filePaths[0], type });
      }
    });
});
// function copy(src: string, target: string) {
//   return new Promise((resolve) => {
//     fs.createReadStream(src)
//       .pipe(fs.createWriteStream(target))
//       .on("finish", resolve);
//   });
// }

function unzip(src: string, target: string) {
  compressing.zip
    .uncompress(src, target, { zipFileNameEncoding: "GBK" })
    .then((r) => {
      console.log("unzip success");
      win.webContents.send("unzip finish", true);
    })
    .catch((error) => {
      win.webContents.send("unzip finish", false);
      dialog.showMessageBox({
        type: "error",
        message: "解压出错，请手动解压",
        title: "出错啦",
      });
      console.log("unzip error", error);
    });
}

ipcMain.on("unzip", (event, { src, target }) => {
  unzip(src, target);
});

ipcMain.on("check version", (event, { force, tips }) => {
  const versionPath = join(store.get("gameDir"), defaultConfig.versionName);
  if (fs.existsSync(versionPath)) {
    try {
      const str = fs.readFileSync(versionPath, "utf-8");
      const oldV = JSON.parse(str);
      win.webContents.send("has install");
      fetch(store.get("version"))
        .then((response) => response.json())
        .then((response) => {
          console.log(
            "compare version",
            response.version > oldV.version ? "need update" : "unneed update"
          );
          win.webContents.send("need update", response.version > oldV.version);
        });
    } catch (error) {
      console.log("check version error", error);
    }
  } else if (force) {
    win.webContents.send("need update", true);
  } else if (tips) {
    dialog.showMessageBox({
      type: "info",
      message: "当前设置不是游戏目录，不支持自动更新",
      title: "检查更新",
    });
  }
});

ipcMain.on("game start", (event) => {
  const exePath = store.get("gameExe");
  if (fs.existsSync(exePath)) {
    const child = exec("start " + exePath);
    child.unref();
  } else {
    dialog.showMessageBox({
      type: "warning",
      message: "未检测到启动程序，请联系管理员",
    });
  }
});

ipcMain.on("reset store", () => {
  store.clear();
  initStore();
  win.webContents.send("set path", store.get("directory"));
});
